#ifndef NCSPROPEDIT_H
#define NCSPROPEDIT_H

#include <ncsppt_export.h>
#include "ncspropmgr.h"
#include <QWidget>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QCheckBox>
#include <QComboBox>


class NcsProp;
class QMouseEvent;
class QLabel; 
class QEvent; 

class NCSPPT_EXPORT NcsPropEdit : public QWidget
{
    Q_OBJECT
public:
    NcsPropEdit(NcsProp* prop, QWidget* parent = nullptr) : QWidget(parent) , m_prop(prop) {}

    virtual void loadPropValue(const NcsProp* prop)  = 0; 

protected:
    NcsProp* m_prop  = nullptr ;
};

class NCSPPT_EXPORT NpLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    NpLineEdit(NcsProp* prop, QWidget* parent = nullptr) 
        : QLineEdit(parent) 
        , m_prop(prop) 
        , m_editor(this)
    {
        if (m_prop) m_editor->setText(prop->value().toString()); 
        m_prevstr = m_editor->text(); 

        // connect 
        connect(m_editor, &QLineEdit::editingFinished, [this] () { slotSetValue(m_editor->text()); });

    }

    virtual void slotSetValue(const QString& s )
    {
        if (m_prevstr == s) return; 
        m_prop->propMgr()->setValue(m_prop, s);
        m_prevstr = s; 
    }

protected:
    QLineEdit* m_editor = nullptr;
    QString    m_prevstr; // previous text in QLineEdit 
    NcsProp*   m_prop  = nullptr ;
}; // NpLineEdit

class NCSPPT_EXPORT NpStringEdit : public NpLineEdit
{
    Q_OBJECT
public:
    NpStringEdit(NcsProp* prop,QWidget* parent = nullptr) : NpLineEdit(prop, parent) 
    {
        m_editor->setText(prop->value().toString()); 
    }
};

class NCSPPT_EXPORT NpIntEdit : public NpLineEdit
{
    Q_OBJECT
public:
    NpIntEdit(NcsProp* prop,QWidget* parent = nullptr) : NpLineEdit(prop, parent) 
    {
        m_editor->setText(QString::number(prop->value().toInt())); 
        m_prevstr = m_editor->text(); 
        m_editor->setValidator(new QIntValidator(m_editor));
    }

    virtual void slotSetValue(const QString& s ) override
    {
        if (m_prevstr == s) return; 
        m_prop->propMgr()->setValue(m_prop, s.toInt());
        m_prevstr = s; 
    }

}; //NpIntEdit


class NCSPPT_EXPORT NpDoubleEdit : public NpLineEdit
{
public:
    NpDoubleEdit(NcsProp* prop,QWidget* parent = nullptr) : NpLineEdit(prop, parent) 
    {
        m_editor->setValidator(new QDoubleValidator(m_editor));
        m_editor->setText(m_prop->value().toString()); 
    }

    virtual void slotSetValue(const QString& s ) override
    {
        if (m_prevstr == s) return; 
        m_prop->propMgr()->setValue(m_prop, s);
        m_prevstr = s; 
    }

}; // NpDoubleEdit

//--------------------------------------------------------------------------------------------------
class NCSPPT_EXPORT NpBoolEdit : public NcsPropEdit
{
public:
	NpBoolEdit(NcsProp* prop, QWidget* parent = nullptr);
    virtual void loadPropValue(const NcsProp* prop) override ;

    bool textVisible() const { return m_textVisible; }
    void setTextVisible(bool textVisible);

protected:
    virtual void mousePressEvent(QMouseEvent * event) override;
    //void paintEvent(QPaintEvent *);
    void updateTextVisible(); 
    QCheckBox* m_checkBox = nullptr;
    bool m_textVisible = true;
};

//--------------------------------------------------------------------------------------------------
class NCSPPT_EXPORT NpComboBox : public QComboBox
{
    Q_OBJECT
public:
    NpComboBox(NcsProp* prop, QWidget* parent = nullptr);

    void setItemAndData(const QStringList& item_labels, QVariantList item_data = {}) ;

public slots:

    /** Set property value to  according to content in item-{index}
     *  Once NpComboBox is subclassed, it's sufficient to override slotSetValue() function only. 
     *
     *  by default NpComboBox will pass the TEXT of item to property's manager. 
     */
    virtual void slotSetValue(int index);  

protected:
    NcsProp*   m_prop = nullptr; 
};

typedef NpComboBox NcsEnumEdit; 
typedef NpComboBox NcsIntEnumEdit; 

class NCSPPT_EXPORT NcsStringEnumEdit: public NpComboBox
{
    Q_OBJECT
public:
    using NpComboBox::NpComboBox; 

    virtual void slotSetValue(int index) override;  
};

//--------------------------------------------------------------------------------------------------
class NCSPPT_EXPORT NcsFontEdit : public NcsPropEdit
{
    Q_OBJECT

public:
    NcsFontEdit(NcsProp* prop, QWidget *parent = nullptr);

    virtual void loadPropValue(const NcsProp* prop) override {}
    bool eventFilter(QObject *obj, QEvent *ev);

public Q_SLOTS:
    void updateProp(const QFont &value);
    void updateEditor(const QFont& value); 

private Q_SLOTS:
    void buttonClicked();

private:
    QFont m_font;
    QLabel *m_pixmapLabel;
    QLabel *m_label;
    QToolButton *m_button;
};

//--------------------------------------------------------------------------------------------------

class NCSPPT_EXPORT NcsColorEdit : public NcsPropEdit
{
    Q_OBJECT

public:
    NcsColorEdit(NcsProp* prop, QWidget *parent = nullptr);

    bool eventFilter(QObject *obj, QEvent *ev);
    virtual void loadPropValue(const NcsProp* prop) override {}

public Q_SLOTS:
    void updateProp(const QColor &value);
    void updateEditor(const QColor &value);

private Q_SLOTS:
    void buttonClicked();

private:
    QColor m_color;
    QLabel *m_pixmapLabel;
    QLabel *m_label;
    QToolButton *m_button;
};


//--------------------------------------------------------------------------------------------------

#endif //NCSPROPEDIT_H

